import matplotlib.pyplot as plt
import numpy as np


class Linear_Regression:

    # 梯度下降，更新w和b
    def gradient_descent(self, w, b, alpha):
        for i in range(self.m):
            x_i = self.data[i][0]
            y_i = self.data[i][1]
            w -= (alpha / self.m) * (w * x_i + b - y_i) * x_i
            b -= (alpha / self.m) * (w * x_i + b - y_i)
        return w, b

    # 计算损失值
    def cal_loss(self, w, b):
        # J表示总损失
        J = 0
        for i in range(self.m):
            x_i = self.data[i][0]
            y_i = self.data[i][1]
            J += 1.0 / (2 * self.m) * pow((w * x_i + b - y_i), 2)
        return J

        # 初始化数据

    def __init__(self):
        # 读取文件a.txt中的数据,分隔符为",",以double格式读取数据
        self.data = np.loadtxt('ex1data1.txt', delimiter=',', dtype=np.float64)
        # m设置行数
        self.m = self.data.shape[0]

        # 数据值
        # 一共2*2，4个图，现在画第一个图
        plt.subplot(2, 2, 1)
        # 显示中文标签
        plt.rcParams["font.sans-serif"] = ["SimHei"]
        plt.rcParams["axes.unicode_minus"] = False
        plt.title("线性回归变量来预测食品卡车的利润")  # 设置x
        plt.xlabel("城市人口，单位万")  # 设置x轴
        plt.ylabel("利润，单位千")  # 设置y轴
        # scatter绘制散点图
        plt.scatter(self.data[:, 0], self.data[:, 1], marker='x')

    # 开始函数
    def main(self):

        alpha = 0.01  # 学习速率
        iterations = 1500  # 梯度下降的迭代轮数
        # 下面两个是带估计的参数值，每次需要更新一下两个值
        w = 0.0
        b = 0.0
        w_all = []
        b_all = []
        # 为损失总函数
        cost = []
        print("-------开始计算了-----")
        # 计算一下损失，初始值损失
        print("初始的损失值",self.cal_loss(w, b))
        # 大概训练1500个回合
        for i in range(iterations):
            w_all.append(w)
            b_all.append(b)
            w, b = self.gradient_descent(w, b, alpha)
            temp = self.cal_loss(w, b)
            cost.append(temp)

        print("最后结果的w---", w, "最后结果的b---", b)
        x = [5.0, 22.5]
        y = [5.0 * w + b, 22.5 * w + b]
        plt.subplot(2, 2, 2)
        plt.plot(x, y, color="red")
        plt.title("线性回归第一题")
        plt.xlabel("城市的人口数量")
        plt.ylabel("利润")
        plt.scatter(self.data[:, 0], self.data[:, 1], marker='x')

        print(str(cost))
        plt.subplot(2, 2, 3)
        plt.title("损失函数J")
        plt.xlabel("迭代次数")
        plt.ylabel("损失值")
        plt.plot(range(len(cost)), cost, color="red")
        plt.show()
        print("损失值", cost[0:5])
        print("b--", b_all[0:5])
        print("w--", w_all[0:5])
        print("-------结束了-----")




if __name__ == '__main__':
    obj = Linear_Regression()
    obj.main()
